`include "DDRStruct.vh"
module io_DDR #(
    parameter integer ADDR_WIDTH = 64,
    parameter integer DATA_WIDTH = 128
) (
    input  clk_100mhz,
    input  clk_200mhz,
    input  rstn,
    output ui_clk,
    output ui_clk_sync_rst,

    DDR_ift.Slave ddr_request,

    inout  [15:0] ddr2_dq,
    inout  [ 1:0] ddr2_dqs_n,
    inout  [ 1:0] ddr2_dqs_p,
    output [12:0] ddr2_addr,
    output [ 2:0] ddr2_ba,
    output        ddr2_ras_n,
    output        ddr2_cas_n,
    output        ddr2_we_n,
    output [ 0:0] ddr2_ck_p,
    output [ 0:0] ddr2_ck_n,
    output [ 0:0] ddr2_cke,
    output [ 0:0] ddr2_cs_n,
    output [ 1:0] ddr2_dm,
    output [ 0:0] ddr2_odt,

    input  DDRStruct::DDRDebugCorePack ddr_debug_core,
    output DDRStruct::DDRDebugPack     ddr_debug
);

    wire [ 63:0] raddr_mem;
    wire [ 63:0] waddr_mem;
    wire [127:0] wdata_mem;
    wire [127:0] rdata_mem;
    wire         rvalid_mem;
    wire         wvalid_mem;
    wire         wen_mem;
    wire         ren_mem;
    wire [ 15:0] wmask_mem;

    wire [ 26:0] app_addr;
    wire [  2:0] app_cmd;
    wire         app_en;
    wire [127:0] app_wdf_data;
    wire         app_wdf_end;
    wire [ 15:0] app_wdf_mask;
    wire         app_wdf_wren;
    wire [127:0] app_rd_data;
    wire         app_rd_data_end;
    wire         app_rd_data_valid;
    wire         app_rdy;
    wire         app_wdf_rdy;
    wire         init_calib_complete;

    wire [  2:0] debug_ddrctrl_state;
    wire         debug_app_en;
    wire         debug_app_wdf_wren;
    wire         debug_app_rdy;
    wire         debug_app_wdf_rdy;
    wire         debug_app_rd_data_valid;

    DDR_Ctrl #(
        .ADDR_WIDTH(ADDR_WIDTH),
        .DATA_WIDTH(DATA_WIDTH)
    ) ddr_ctrl (
        .ui_clk         (ui_clk),
        .ui_clk_sync_rst(ui_clk_sync_rst),
        .raddr_mem      (raddr_mem),
        .waddr_mem      (waddr_mem),
        .wdata_mem      (wdata_mem),
        .rdata_mem      (rdata_mem),
        .wvalid_mem     (wvalid_mem),
        .rvalid_mem     (rvalid_mem),
        .wen_mem        (wen_mem),
        .ren_mem        (ren_mem),
        .wmask_mem      (wmask_mem),

        .app_addr           (app_addr),
        .app_cmd            (app_cmd),
        .app_en             (app_en),
        .app_wdf_data       (app_wdf_data),
        .app_wdf_end        (app_wdf_end),
        .app_wdf_mask       (app_wdf_mask),
        .app_wdf_wren       (app_wdf_wren),
        .app_rd_data        (app_rd_data),
        .app_rd_data_end    (app_rd_data_end),
        .app_rd_data_valid  (app_rd_data_valid),
        .app_rdy            (app_rdy),
        .app_wdf_rdy        (app_wdf_rdy),
        .init_calib_complete(init_calib_complete),

        .debug_ddrctrl_state    (debug_ddrctrl_state),
        .debug_app_en           (debug_app_en),
        .debug_app_wdf_wren     (debug_app_wdf_wren),
        .debug_app_rdy          (debug_app_rdy),
        .debug_app_wdf_rdy      (debug_app_wdf_rdy),
        .debug_app_rd_data_valid(debug_app_rd_data_valid)
    );

    assign waddr_mem              = ddr_request.waddr_mem;
    assign raddr_mem              = ddr_request.raddr_mem;
    assign ren_mem                = ddr_request.ren_mem;
    assign wen_mem                = ddr_request.wen_mem;
    assign ddr_request.rdata_mem  = rdata_mem;
    assign ddr_request.rvalid_mem = rvalid_mem;
    assign ddr_request.wvalid_mem = wvalid_mem;
    assign wdata_mem              = ddr_request.wdata_mem;
    assign wmask_mem              = ddr_request.wmask_mem;

    mig_7series_0 u_my_ddr (
        // Memory interface ports
        .ddr2_cs_n          (ddr2_cs_n),
        .ddr2_addr          (ddr2_addr),
        .ddr2_ba            (ddr2_ba),
        .ddr2_we_n          (ddr2_we_n),
        .ddr2_ras_n         (ddr2_ras_n),
        .ddr2_cas_n         (ddr2_cas_n),
        .ddr2_ck_n          (ddr2_ck_n),
        .ddr2_ck_p          (ddr2_ck_p),
        .ddr2_cke           (ddr2_cke),
        .ddr2_dq            (ddr2_dq),
        .ddr2_dqs_n         (ddr2_dqs_n),
        .ddr2_dqs_p         (ddr2_dqs_p),
        .ddr2_dm            (ddr2_dm),
        .ddr2_odt           (ddr2_odt),
        // Application interface ports
        .app_addr           (app_addr),
        .app_cmd            (app_cmd),
        .app_en             (app_en),
        .app_wdf_rdy        (app_wdf_rdy),
        .app_wdf_data       (app_wdf_data),
        .app_wdf_end        (app_wdf_end),
        .app_wdf_wren       (app_wdf_wren),
        .app_wdf_mask       (app_wdf_mask),
        .app_rd_data        (app_rd_data),
        .app_rd_data_end    (app_rd_data_end),
        .app_rd_data_valid  (app_rd_data_valid),
        .app_rdy            (app_rdy),
        .app_sr_req         (1'b0),
        .app_sr_active      (),
        .app_ref_req        (1'b0),
        .app_ref_ack        (),
        .app_zq_req         (1'b0),
        .app_zq_ack         (),
        .init_calib_complete(init_calib_complete),
        .ui_clk             (ui_clk),
        .ui_clk_sync_rst    (ui_clk_sync_rst),
        // System Clock Ports
        .sys_clk_i          (clk_100mhz),
        // Reference Clock Ports
        .clk_ref_i          (clk_200mhz),
        .sys_rst            (rstn)
    );

    assign ddr_debug.debug_ddrctrl_state     = debug_ddrctrl_state;
    assign ddr_debug.debug_app_en            = debug_app_en;
    assign ddr_debug.debug_app_wdf_wren      = debug_app_wdf_wren;
    assign ddr_debug.debug_app_rdy           = debug_app_rdy;
    assign ddr_debug.debug_app_wdf_rdy       = debug_app_wdf_rdy;
    assign ddr_debug.debug_app_rd_data_valid = debug_app_rd_data_valid;
    assign ddr_debug.ddr_debug_core          = ddr_debug_core;

endmodule
